로딩 중이에요... 🐣
[코담]
웹개발·실전 프로젝트·AI까지, 파이썬·장고의 모든것을 담아낸 강의와 개발 노트
07 Form 처리와 Generic View 활용 | ✅ 편저: 코담 운영자
Django 웹 프로그래밍 강좌 7강 - Form 처리와 Generic View 활용 (Django 5.2 기준)
이 강의는 Django 공식 문서의 2.2 튜토리얼 내용을 바탕으로 진행되며, Django 5.2 버전에 맞춰 코드를 업그레이드하여 설명합니다.
📚 공식문서 주소: https://docs.djangoproject.com/ko/5.2/intro/tutorial04/
1. 사용자 입력 처리: Form 태그 구조 이해
HTML의 <form>
태그는 사용자의 입력을 서버로 전달하는 핵심 구조입니다.
detail.html
내 form 구성 예시:
<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
{% for choice in question.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}">
<label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
{% endfor %}
<input type="submit" value="Vote">
</form>
action
: 데이터를 보낼 URL 경로method="post"
: 데이터를 서버로 전송하는 방식{% csrf_token %}
: Django 보안을 위한 필수 태그radio
: 단일 항목 선택을 위한 입력 필드value
: 선택된 항목의 고유 ID
Django는 CSRF 공격을 방지하기 위해 POST 요청 시 보안 토큰을 요구합니다.
2. Form에서 View로 데이터 처리 흐름
vote()
뷰 함수 (polls/views.py
):
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect
from django.urls import reverse
from .models import Question, Choice
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected_choice = question.choice_set.get(pk=request.POST["choice"])
except (KeyError, Choice.DoesNotExist):
return render(request, "polls/detail.html", {
"question": question,
"error_message": "선택이 필요합니다.",
})
else:
selected_choice.votes += 1
selected_choice.save()
return HttpResponseRedirect(reverse("polls:results", args=(question.id,)))
request.POST["choice"]
로 전송된 데이터 추출- 선택값이 없거나 잘못된 경우 예외 처리 후 에러 메시지 출력
- 올바른 선택이면 vote 수 증가 후 저장 → 결과 페이지로 리디렉션
reverse()
함수는 URL 패턴 이름 기반으로 URL을 생성하며, 하드코딩을 방지합니다.
3. 결과 페이지 구성
결과 View (polls/views.py
):
def results(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, "polls/results.html", {"question": question})
결과 템플릿 (polls/templates/polls/results.html
):
<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.choice_text }} — {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>
<a href="{% url 'polls:detail' question.id %}">다시 투표하기</a>
pluralize
필터는 1표 vs 복수 표의 언어 처리에 유용
4. 함수 기반 View vs 클래스 기반 View (Generic View)
Django는 중복되는 View 코드를 줄이기 위해 Generic Class-Based Views(CBV)를 제공합니다.
Generic View 예시 (views.py
):
from django.views import generic
from .models import Question
class IndexView(generic.ListView):
template_name = "polls/index.html"
context_object_name = "latest_question_list"
def get_queryset(self):
return Question.objects.order_by("-pub_date")[:5]
class DetailView(generic.DetailView):
model = Question
template_name = "polls/detail.html"
class ResultsView(generic.DetailView):
model = Question
template_name = "polls/results.html"
ListView
: 객체 목록 뷰DetailView
: 특정 객체 상세 뷰get_queryset()
은 보여줄 데이터 범위 지정
URLconf 변경 (polls/urls.py
):
from . import views
app_name = "polls"
urlpatterns = [
path("", views.IndexView.as_view(), name="index"),
path("<int:pk>/", views.DetailView.as_view(), name="detail"),
path("<int:pk>/results/", views.ResultsView.as_view(), name="results"),
path("<int:question_id>/vote/", views.vote, name="vote"),
]
- Generic View는 기본적으로
pk
파라미터를 객체 식별자로 사용합니다.
Generic View는 빠른 개발을 가능하게 하며, 반복 코드를 줄일 수 있습니다.
마무리 요약
- Form을 통해 사용자 입력을 서버로 전달하고 처리 가능
- CSRF 보호와 POST 방식은 Django에서 기본 보안 요소
request.POST[]
로 입력값 추출 후, 모델에 반영하여 저장reverse()
를 사용하여 URL 하드코딩을 방지- Generic View는 클래스를 기반으로 반복 코드를 줄이고, 유지보수가 쉽다
다음 강의 예고
8강에서는 **단위 테스트(TestCase)**를 사용하여 뷰와 모델의 동작을 자동으로 검증하는 방법을 학습합니다.
감사합니다.